package com.example.yx.demo26;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.method.annotation.*;
import org.springframework.web.util.UrlPathHelper;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class A26 {
    private static final Logger log = LoggerFactory.getLogger(A26.class);

    public static void main(String[] args) throws Exception{
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(WebConfig.class);
//        test1();
//        test2();
//        test3();
//        test4();
//        test5();

//        test6();
        test7();
    }


    private static void test1() throws Exception {
        Method method = Controller.class.getMethod("test1");
        Controller controller = new Controller();
        Object resultValue = method.invoke(controller);

        HandlerMethod handlerMethod = new HandlerMethod(controller,method);
        ModelAndViewContainer container = new ModelAndViewContainer();
        MockHttpServletRequest request = new MockHttpServletRequest();

        //1.测试返回值类型为ModelAndView
        HandlerMethodReturnValueHandlerComposite composite = getReturnValueHandler();
        //检查是否支持此类型的返回值
        if (composite.supportsReturnType(handlerMethod.getReturnType())) {
            composite.handleReturnValue(resultValue,handlerMethod.getReturnType(),container,new ServletWebRequest(request));
            System.out.println(container.getModel());
            System.out.println(container.getViewName());
        }
    }

    private static void test2() throws Exception {
        Method method = Controller.class.getMethod("test2");
        Controller controller = new Controller();
        Object resultValue = method.invoke(controller);

        HandlerMethod handlerMethod = new HandlerMethod(controller,method);
        ModelAndViewContainer container = new ModelAndViewContainer();
        MockHttpServletRequest request = new MockHttpServletRequest();

        //1.测试返回值类型为String
        HandlerMethodReturnValueHandlerComposite composite = getReturnValueHandler();
        //检查是否支持此类型的返回值
        if (composite.supportsReturnType(handlerMethod.getReturnType())) {
            composite.handleReturnValue(resultValue,handlerMethod.getReturnType(),container,new ServletWebRequest(request));
            System.out.println(container.getModel());
            System.out.println(container.getViewName());
        }
    }

    private static void test3() throws Exception {
        Method method = Controller.class.getMethod("test3");
        Controller controller = new Controller();
        Object resultValue = method.invoke(controller);

        HandlerMethod handlerMethod = new HandlerMethod(controller,method);
        ModelAndViewContainer container = new ModelAndViewContainer();
        MockHttpServletRequest request = new MockHttpServletRequest();
//        //视图名为null挽救方法
//        request.setRequestURI("/test3");
//        UrlPathHelper.defaultInstance.resolveAndCacheLookupPath(request);
        //3.测试@ModelAttribute
        HandlerMethodReturnValueHandlerComposite composite = getReturnValueHandler();
        //检查是否支持此类型的返回值
        if (composite.supportsReturnType(handlerMethod.getReturnType())) {
            composite.handleReturnValue(resultValue,handlerMethod.getReturnType(),container,new ServletWebRequest(request));
            System.out.println(container.getModel());
            System.out.println(container.getViewName());
        }
    }

    private static void test4() throws Exception {
        Method method = Controller.class.getMethod("test4");
        Controller controller = new Controller();
        Object resultValue = method.invoke(controller);

        HandlerMethod handlerMethod = new HandlerMethod(controller,method);
        ModelAndViewContainer container = new ModelAndViewContainer();
        MockHttpServletRequest request = new MockHttpServletRequest();
//        //视图名为null挽救方法
//        request.setRequestURI("/test3");
//        UrlPathHelper.defaultInstance.resolveAndCacheLookupPath(request);
        //3.测试@ModelAttribute
        HandlerMethodReturnValueHandlerComposite composite = getReturnValueHandler();
        //检查是否支持此类型的返回值
        if (composite.supportsReturnType(handlerMethod.getReturnType())) {
            composite.handleReturnValue(resultValue,handlerMethod.getReturnType(),container,new ServletWebRequest(request));
            System.out.println(container.getModel());
            System.out.println(container.getViewName());
        }
    }

    private static void test5() throws Exception {
        Method method = Controller.class.getMethod("test5");
        Controller controller = new Controller();
        Object resultValue = method.invoke(controller);

        HandlerMethod handlerMethod = new HandlerMethod(controller,method);
        ModelAndViewContainer container = new ModelAndViewContainer();
        MockHttpServletRequest request = new MockHttpServletRequest();
        MockHttpServletResponse response = new MockHttpServletResponse();
//        //视图名为null挽救方法
//        request.setRequestURI("/test3");
//        UrlPathHelper.defaultInstance.resolveAndCacheLookupPath(request);
        //3.测试@ModelAttribute
        HandlerMethodReturnValueHandlerComposite composite = getReturnValueHandler();
        ServletWebRequest webRequest = new ServletWebRequest(request, response);
        //检查是否支持此类型的返回值
        if (composite.supportsReturnType(handlerMethod.getReturnType())) {
            composite.handleReturnValue(resultValue,handlerMethod.getReturnType(),container,webRequest);
            System.out.println(container.getModel());
            System.out.println(container.getViewName());
        }
    }

    private static void test6() throws Exception {
        Method method = Controller.class.getMethod("test6");
        Controller controller = new Controller();
        Object resultValue = method.invoke(controller);

        HandlerMethod handlerMethod = new HandlerMethod(controller,method);
        ModelAndViewContainer container = new ModelAndViewContainer();
        MockHttpServletRequest request = new MockHttpServletRequest();
        MockHttpServletResponse response = new MockHttpServletResponse();
//        //视图名为null挽救方法
//        request.setRequestURI("/test3");
//        UrlPathHelper.defaultInstance.resolveAndCacheLookupPath(request);
        //3.测试@ModelAttribute
        HandlerMethodReturnValueHandlerComposite composite = getReturnValueHandler();
        ServletWebRequest webRequest = new ServletWebRequest(request, response);
        //检查是否支持此类型的返回值
        if (composite.supportsReturnType(handlerMethod.getReturnType())) {
            composite.handleReturnValue(resultValue,handlerMethod.getReturnType(),container,webRequest);
            System.out.println(container.getModel());
            System.out.println(container.getViewName());
            for (String name : response.getHeaderNames()) {
                System.out.println(name + " : " + response.getHeader(name));
            }
        }
    }

    private static void test7() throws Exception {
        Method method = Controller.class.getMethod("test7");
        Controller controller = new Controller();
        Object resultValue = method.invoke(controller);

        HandlerMethod handlerMethod = new HandlerMethod(controller,method);
        ModelAndViewContainer container = new ModelAndViewContainer();
        MockHttpServletRequest request = new MockHttpServletRequest();
        MockHttpServletResponse response = new MockHttpServletResponse();
//        //视图名为null挽救方法
//        request.setRequestURI("/test3");
//        UrlPathHelper.defaultInstance.resolveAndCacheLookupPath(request);
        //3.测试@ModelAttribute
        HandlerMethodReturnValueHandlerComposite composite = getReturnValueHandler();
        ServletWebRequest webRequest = new ServletWebRequest(request, response);
        //检查是否支持此类型的返回值
        if (composite.supportsReturnType(handlerMethod.getReturnType())) {
            composite.handleReturnValue(resultValue,handlerMethod.getReturnType(),container,webRequest);
            System.out.println(container.getModel());
            System.out.println(container.getViewName());
            for (String name : response.getHeaderNames()) {
                System.out.println(name + " : " + response.getHeader(name));
            }
        }
    }


    //返回值处理器
    public static HandlerMethodReturnValueHandlerComposite getReturnValueHandler() {
        HandlerMethodReturnValueHandlerComposite composite = new HandlerMethodReturnValueHandlerComposite();
        composite.addHandler(new ModelAndViewMethodReturnValueHandler());
        composite.addHandler(new ViewNameMethodReturnValueHandler());
        composite.addHandler(new ServletModelAttributeMethodProcessor(false));

        List<HttpMessageConverter<?>> list = new ArrayList<>();
        list.add(new MappingJackson2HttpMessageConverter());
        composite.addHandler(new HttpEntityMethodProcessor(list));
        composite.addHandler(new HttpHeadersReturnValueHandler());
        composite.addHandler(new RequestResponseBodyMethodProcessor(list));
        composite.addHandler(new ServletModelAttributeMethodProcessor(true));
        return composite;
    }

    static class Controller {
        private static final Logger log = LoggerFactory.getLogger(Controller.class);

        public ModelAndView test1() {
            log.debug("test1()");
            ModelAndView mav = new ModelAndView("view1");
            mav.addObject("name","张三");
            return mav;
        }

        public String test2() {
            log.debug("test2()");
            return "view2";
        }

        @ModelAttribute
        public User test3() {
            log.debug("test3()");
            return new User("李四",20);
        }

        public User test4() {
            log.debug("test4()");
            return new User("王五",30);
        }

        public HttpEntity<User> test5() {
            log.debug("test5()");
            return new HttpEntity<>(new User("赵六",40));
        }

        public HttpHeaders test6() {
            log.debug("test6()");
            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.add("Content-Type","text/html");
            return httpHeaders;
        }

        @ResponseBody
        public User test7() {
            log.debug("test7()");
            return new User("钱七",50);
        }
    }

    static class User{
        private String name;
        private int age;

        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        public User(String name, int age) {
            this.name = name;
            this.age = age;
        }
    }
}
